<script setup lang="ts">
import { ref, onMounted, watch, onUnmounted } from "vue";
import Vditor from 'vditor'
import { Plus, Delete, Star } from "@element-plus/icons-vue";
import SvgIcon from "../utils/SvgIcon.vue";
import { userStore } from "../../store";
import { storeToRefs } from "pinia";
import { ElMessage } from "element-plus";
import { NoteBook, SqliteDatabase } from '../../utils/database'
import { invoke } from "@tauri-apps/api/core";
import { open as dialogOpen, save as dialogSave } from '@tauri-apps/plugin-dialog'
import { open } from '@tauri-apps/plugin-fs'

let book: SqliteDatabase


const menuList = ref<NoteBook[]>()
const currentNote = ref<string>()
const currentMenu = ref<NoteBook>()

const menuHeight = ref()
const editor = ref()
const store = userStore()
const content = ref('')
const storeRef = storeToRefs(store)

watch(storeRef.mode, () => {
    const mode = storeRef.mode.value ? 'classic' : 'dark'
    editor.value.setTheme(mode, mode, 'vs')
}, { deep: true })

const getFileMTime = async (filepath: string) => {
    const file = await open(filepath)
    const mTime = (await file.stat()).mtime.toLocaleString() as string
    await file.close()
    return mTime
}

const createFile = () => {
    currentMenu.value = undefined
    currentNote.value = ''
    content.value = ''
    editor.value.setValue('')
}
const deleteFile = async () => {
    if (currentMenu === undefined) {
        ElMessage({
            message: '当前无选中文件',
            type: 'warning'
        })
        return
    }
    const filepath = `${currentMenu.value.folder}\\${currentMenu.value.title}.${currentMenu.value.type}`
    await invoke('delete_file', { filepath: filepath })
    await book.removeData(currentMenu.value.id)
    ElMessage({
        message: '删除成功',
        type: 'success'
    })
    // 删除完毕，重置menuList数据
    const data = await book.queryAllData() as Array<NoteBook>
    menuList.value = data
    if (data.length === 0) {
        currentMenu.value = undefined
        currentNote.value = ''
        editor.value.setValue('')
        return
    }
    currentMenu.value = data[0]
    currentNote.value = data[0].title + '.' + data[0].id
    const file = `${data[0].folder}\\${data[0].title}.${data[0].type}`
    content.value = await readFile(file) as string
    editor.value.setValue(content.value)
}
const saveFile = async () => {
    const contentFile = editor.value.getValue()
    // 保存文件 1. 文件不存在的时候需要打开保存文件dialog
    if (currentMenu.value === undefined) {
        // 新建的文件
        const filepath = await dialogSave({
            filters: [{ name: 'Markdown File', extensions: ['md', 'markdown'] }]
        })
        if (filepath === null) {
            ElMessage({
                message: '文件保存失败',
                type: 'error'
            })
            return
        }
        const data: NoteBook = {
            title: filepath.slice(filepath.lastIndexOf('\\') + 1).split('.')[0],
            folder: filepath.slice(0, filepath.lastIndexOf('\\')),
            type: filepath.slice(filepath.lastIndexOf('\\') + 1).split('.')[1],
        }
        const res = await book.queryDataAny(data)
        await invoke('write_file', { filepath: filepath, content: contentFile })
        const mTime = await getFileMTime(filepath)
        data.mTime = mTime
        if (res.length === 0) {
            // 往数据库中插入数据
            data.collect = '0'
            const temp = await book.insertData(data)
            data.id = temp.lastInsertId

            console.log(data)

            menuList.value = (await book.queryAllData()) as Array<NoteBook>
            currentMenu.value = data
            currentNote.value = data.title + '.' + data.id

            content.value = await readFile(filepath) as string
            editor.value.setValue(content.value)
        } else {
            await book.updateData(res[0].id, { mTime: mTime })
            currentNote.value = res[0].title + '.' + res[0].id
            currentMenu.value = res[0]
        }
    } else {
        const filepath = `${currentMenu.value.folder}\\${currentMenu.value.title}.${currentMenu.value.type}`
        await invoke('write_file', { filepath: filepath, content: contentFile })
        const mTime = await getFileMTime(filepath)
        await book.updateData(currentMenu.value.id, { mTime: mTime })
    }
    ElMessage({
        message: '保存成功',
        type: 'success'
    })
}
const exportFile = async () => {
    // 支持两种格式，pdf与html格式
    const filepath = await dialogSave({
        filters: [
            { name: 'HTML File', extensions: ['html', 'hml'] },
            { name: 'PDF File', extensions: ['pdf'] }
        ]
    })
    if (filepath === null) {
        ElMessage({
            message: '文件导出失败',
            type: 'error'
        })
        return
    }
    const filetype = filepath.split('.')[1]
    const contentFile = filetype === 'pdf' ? editor.value.getValue() : editor.value.getHTML()
    invoke('export_file', { filepath: filepath, filetype: filetype, content: contentFile })
}
const collectFile = async () => {
    const collect = currentMenu.value.collect === '0' ? '1' : '0'
    const res = await book.updateData(currentMenu.value.id, { collect: collect })
    if (res !== null) {
        ElMessage({
            message: collect === '0' ? '取消收藏成功' : '收藏成功',
            type: 'success'
        })
        currentMenu.value.collect = collect
        menuList.value = await book.queryAllData() as Array<NoteBook>
    } else {
        ElMessage({
            message: '操作失败',
            type: 'error'
        })
    }
}

const uploadFile = async () => {
    const file = await dialogOpen({
        multiple: false,
        directory: false,
        filters: [{ name: 'Markdown File', extensions: ['md', 'markdown'] }]
    });
    if (file === null) {
        ElMessage({
            message: '文件上传失败',
            type: 'error'
        })
        return
    }
    const mTime = await getFileMTime(file)

    // 存在正确的文件
    const data: NoteBook = {
        title: file.slice(file.lastIndexOf('\\') + 1).split('.')[0],
        folder: file.slice(0, file.lastIndexOf('\\')),
        collect: '0',
        type: file.slice(file.lastIndexOf('\\') + 1).split('.')[1],
        mTime: mTime,
    }
    const res = await book.queryDataAny(data)
    if (res.length === 0) {
        // 数据不存在，可以存入数据库
        const temp = await book.insertData(data)
        data.id = temp.lastInsertId
        ElMessage({
            message: '文件上传成功！',
            type: 'success'
        })
        // 更新menuList
        menuList.value = (await book.queryAllData()) as Array<NoteBook>
        currentMenu.value = data
        currentNote.value = data.title + '.' + data.id

        content.value = await readFile(file) as string
        editor.value.setValue(content.value)
    } else {
        ElMessage({
            message: '文件已存在，请勿多次上传！',
            type: 'warning'
        })
    }
}

const setMenu = async (event: any) => {
    const index = parseInt(event.index.split('.')[1])
    const data = menuList.value.filter(item => { return item.id === index })[0]
    currentNote.value = data.title + '.' + data.id
    currentMenu.value = data
    const filepath = `${data.folder}\\${data.title}.${data.type}`
    content.value = await readFile(filepath) as string
    editor.value.setValue(content.value)
}

const readFile = async (filepath: string) => {
    return await invoke("read_file", { filepath: filepath })
}

const buttonList = [
    {
        icon: Plus,
        tips: '新建文件',
        flag: true,
        click: createFile,
        color: 'primary'
    },
    {
        svg: 'save',
        tips: '保存文件',
        flag: false,
        click: saveFile,
        color: 'success'
    },
    {
        icon: Delete,
        tips: '删除文件',
        flag: true,
        click: deleteFile,
        color: 'info'
    },
    {
        icon: Star,
        tips: '收藏文件',
        flag: true,
        click: collectFile,
        color: 'warning'
    },
    {
        svg: 'export',
        tips: '导出文件',
        flag: false,
        click: exportFile,
        color: 'danger'
    },
    {
        svg: 'upload',
        tips: '上传文件',
        flag: false,
        click: uploadFile,
        color: 'success'
    },
]

onMounted(async () => {
    book = new SqliteDatabase('notebook')
    await book.open()
    await book.createTable()
    const cardElement = document.getElementsByClassName('vditor-body')[0]
    if (editor.value === undefined) {
        editor.value = new Vditor('vditor', {
            mode: 'ir',
            height: cardElement.clientHeight - 50,
            toolbar: [],
            typewriterMode: true,
            cache: {
                enable: false,
            },
            preview: {
                hljs: { enable: false },
            },
            after: () => {
                editor.value.setValue(content.value)
                const mode = storeRef.mode.value ? 'classic' : 'dark'
                editor.value.setTheme(mode, mode, 'vs')
            }
        })
    }
    const element = document.getElementsByClassName('card-send')[0] as HTMLElement
    menuHeight.value = element.clientHeight - 80

    // 查询全部的数据
    const data = await book.queryAllData() as Array<NoteBook>
    if (data.length === 0) return
    menuList.value = data
    currentMenu.value = data[0]
    currentNote.value = data[0].title + '.' + data[0].id
    const filepath = `${data[0].folder}\\${data[0].title}.${data[0].type}`
    content.value = await readFile(filepath) as string
    editor.value.setValue(content.value)
})

onUnmounted(async () => {
    editor.value.destroy()
    await book.close()
})

window.addEventListener('resize', () => {
    const cardElement = document.getElementsByClassName('vditor-body')[0] as HTMLElement
    (document.getElementById('vditor') as HTMLElement).style.height = `${cardElement.clientHeight - 50}px`
    const element = document.getElementsByClassName('card-send')[0] as HTMLElement
    menuHeight.value = element.clientHeight - 80
})

/**
 * 接受来自electron的数据
 */
// 获取全部文件内容，以及读取单个文件内容


</script>

<template>
    <div style="height: 100%; position: relative;">
        <div style="width: 250px; position:absolute; top: 0; bottom: 0">
            <el-card style="height: 100%" body-style="padding: 8px;
            height: 100% " body-class="card-send">
                <!--文件列表-->
                <el-menu :default-active="currentNote" style="height: 100%; border-right: none">
                    <el-scrollbar height="calc(100% - 20px)">
                        <el-menu-item :index="menu.title + '.' + menu.id" v-for="menu in menuList" @click="setMenu"
                            style="border-right: none">
                            <template #title>{{ menu.title }}</template>
                            <el-icon>
                                <svg-icon name="star" v-if="menu.collect === '1'"></svg-icon>
                                <svg-icon name="lineStar" v-else></svg-icon>
                            </el-icon>
                        </el-menu-item>
                    </el-scrollbar>
                </el-menu>
            </el-card>
        </div>
        <div style="position:absolute; top: 0; bottom: 0; right: 0; left: 255px">
            <el-card style="height: 100%" body-class="vditor-body"
                body-style="height: calc(100% - 20px); padding: 8px;">
                <div style="text-align: end;">
                    <el-tooltip class="box-item" effect="dark" :content="item.tips" placement="top-start"
                        v-for="item in buttonList">
                        <el-button :type="item.color" v-if="item.flag" circle @click="item.click" :icon="item.icon" />
                        <el-button :type="item.color" v-else circle @click="item.click">
                            <svg-icon :name="item.svg" />
                        </el-button>
                    </el-tooltip>
                </div>
                <div id="vditor" class="editor__content" style="margin-top: 10px;" />
            </el-card>
        </div>
    </div>
</template>

<style scoped>
:deep(.vditor-ir pre.vditor-reset:after) {
    height: 20px;
}

:deep(.vditor-toolbar) {
    border: none;
}

#vditor {
    border: none;
}

:deep(.vditor-reset) {
    background-color: var(--el-fill-color-blank, var(--el-fill-color-blank));
    border: none;
    box-sizing: border-box;
    border-radius: var(--el-border-radius-base, var(--el-border-radius-base)) !important;
    box-shadow: 0 0 0 1px var(--el-border-color, var(--el-border-color)) inset !important;
}

:deep(.vditor-reset:hover) {
    box-shadow: 0 0 0 1px var(--el-border-color-hover) inset !important;
}

:deep(.vditor-reset:focus) {
    box-shadow: 0 0 0 1px var(--el-color-primary) inset !important;
}
</style>